package com.test.concurrency;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

class NIOBlocked implements Runnable{
	
	private final SocketChannel sc;
	public NIOBlocked(SocketChannel sc){
		this.sc = sc;
	}
	@Override
	public void run() {
		
		try {
			System.out.println("Waiting for read() in "+this);
			sc.read(ByteBuffer.allocate(1));
			
		} catch(ClosedByInterruptException e){
			System.out.println("ClosedByInterruptException");
		} catch(AsynchronousCloseException e){
			System.out.println("AsynchronousCloseException");
		}catch(IOException e	){
			e.printStackTrace();
		}
		System.out.println("Exiting NIOBlocked.run() "+this);
	}
	
}
public class NIOnterruption {
	public static void main(String[] args)throws Exception{
		ExecutorService exec = Executors.newCachedThreadPool();
		ServerSocket server = new ServerSocket(8082);
		InetSocketAddress isa = new InetSocketAddress("localhost",8082);
		SocketChannel sc1 = SocketChannel.open(isa);
		SocketChannel sc2 = SocketChannel.open(isa);
		Future<?> f = exec.submit(new NIOBlocked(sc1));
		exec.execute(new NIOBlocked(sc2));
		exec.shutdown();
		TimeUnit.SECONDS.sleep(1);
		//produce an interrupt via cancel:
		//closed by interruptException
		f.cancel(true);
		TimeUnit.SECONDS.sleep(1);
		//release the block by closing the channel:
		//AsynchronousCloseException
		sc2.close();
	}
}
